<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css" />
  <script src="https://unpkg.com/vue@next"></script>
  <script src="https://unpkg.com/element-plus"></script>
  <style>
    body {
      padding: 0;
      margin: 0;
      color: #333;
      font-size: 14px;
    }

    hr {
      border: 0;
      border-top: 1px solid #ddd;
    }

    h1 {
      margin: 0;
      font-size: 1.2em;
    }

    .home {
      height: 100vh;
      width: 100vw;
      overflow: hidden;
    }

    .home>header {
      background-color: #409eff;
      display: flex;
      justify-content: space-between;
      align-items: center;
      color: #fff;
    }

    /* 侧边栏 */
    .sidebar {
      height: 100%;
      box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.12);
    }

    .sidebar span {
      margin-left: 10px;
    }

    .sidebar li.is-active path,
    .sidebar li.is-active rect {
      stroke: #409eff;
    }

    .main {
      background-color: #fbfafa;
      padding: 10px 20px;
      padding-bottom: 20px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      height: 100%;
      overflow: hidden;
    }

    .main>header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding-bottom: 10px;
      border-bottom: 1px solid #ddd;
      font-weight: bold;
    }

    .main .nav-title,
    .main .search {
      width: 300px;
    }

    .search {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .search .el-input {
      margin: 0 10px;
    }

    .project-container {
      display: flex;
      flex-direction: column;
      flex: 1
    }

    .project-list {
      display: flex;
      flex-direction: row;
      overflow: auto;
      flex-wrap: wrap;
      padding: 5px;
    }

    .file-item {
      width: 130px;
      height: 130px;
      cursor: pointer;
      margin: 10px;
    }


    .file-item .item {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: space-between;
    }

    .file-item .item img {
      display: inline-block;
    }

    .file-item .item i {
      flex: 1;
      display: flex;
      align-items: center;
    }

    .file-item .file-info {
      width: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    .project-name {
      max-width: calc(100% - 30px);
      padding-right: 5px;
    }

    .icon,
    .icon-btn,
    .icon-btn-stroke {
      cursor: pointer;
    }

    /* 奇怪的 bug，点击会选中 */
    .icon-btn-stroke:focus {
      outline: none;
    }

    .icon-btn:hover path {
      fill: #79bbff;
      transition: all .25s ease-in;
    }

    .icon-btn-stroke:hover path {
      stroke: #79bbff;
      transition: all .25s ease-in;
    }

    .dialog {
      border-radius: 5px;
    }

    .dialog header {
      margin-right: 0;
      padding: 20px 20px 12px 20px;
      box-sizing: border-box;
      border-radius: 5px 5px 0 0;
      background-color: #409eff;
    }

    .dialog footer {
      padding-top: 0;
      display: flex;
      justify-content: center;
    }

    .dialog footer button {
      padding: 16px 40px;
    }

    .dialog header span {
      color: #fff;
      font-weight: bold;
    }

    .dialog header svg path {
      fill: #fff;
    }

    .dialog-form {
      width: 100%;
      box-sizing: border-box;
      padding: 0 40px;
    }

    .pagination {
      display: flex;
      justify-content: center;
    }

    /* 下拉框 */
    .dropdown {
      width: 140px;
      display: flex;
      justify-content: space-between;
    }

    .dropdown>span {
      margin-right: 5px;
    }

    /* 上传 */
    .upload {
      display: flex;
      align-items: center;
    }

    /* 删除 右键菜单 */
    .context-menu {
      position: absolute;
      display: flex;
      flex-direction: column;
      width: 100px;
      background-color: #fff;
      top: 0;
      left: 0;
      padding: 2px;
      border-radius: 5px;
      box-shadow: 0 0 12px 0 rgba(0, 0, 0, 0.12);
    }

    .context-menu button {
      background-color: #fff;
      border: none;
      padding: 6px 10px;
      color: #333;
    }

    .context-menu button:hover {
      background-color: #dcedff;
      color: #409eff;
      cursor: pointer;
    }

    .file-item[data-target] {
      background-color: #e9f0f8;
    }

    /* 多余字省略 */
    .ellipsis-text-overflow {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  </style>
</head>

<body>
  <div id="App">
    <el-container class="home">
      <el-header>
        <h1>Jupyter协作平台</h1>

        <!-- 头像 -->
        <span class="user">
          <el-dropdown>
            <span class="el-dropdown-link">
              <user />
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item class="dropdown">
                  <span v-text="'用户名：' + userName" class="ellipsis-text-overflow"></span>
                  <copy @click="copy"></copy>
                </el-dropdown-item>
                <el-dropdown-item divided style="justify-content:center;">退出登录</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </span>
      </el-header>
      <el-container style="height:100%; width:100%; overflow:hidden;">

        <!-- main 中的侧边栏 -->
        <el-col :span="4">
          <el-menu default-active="1" class="sidebar">
            <el-menu-item index="1">
              <el-icon>
                <sidebar-proj />
              </el-icon>
              <span>项目文件</span>
            </el-menu-item>
            <el-menu-item index="2">
              <el-icon>
                <sidebar-coop />
              </el-icon>
              <span>协作文件</span>
            </el-menu-item>
          </el-menu>
        </el-col>
        <el-col :span="20" class="main">

          <!-- main 中的顶部 -->
          <header>
            <el-breadcrumb separator=">">
              <el-breadcrumb-item :to="{ path: '/' }">项目文件</el-breadcrumb-item>
              <el-breadcrumb-item :to="{ path: '/' }">
                <span v-text="projectName"></span>
              </el-breadcrumb-item>
              <el-breadcrumb-item>历史存档记录</el-breadcrumb-item>
            </el-breadcrumb>
            <!-- 搜索框 -->
            <span class="search">
              <el-input v-model="searchContent" placeholder="请输入搜索内容" size="large" @keyup.enter="search">
                <template #suffix>
                  <search @click="search" />
                </template>
              </el-input>
            </span>
          </header>

          <!-- main 中的项目列表 -->
          <el-main class="project-container">
            <section class="project-list">
              <!-- TODO: handleOpen -->
              <file-item v-for="item in files" :name="item.fileName" :type="item.type" :url="item.url" :id="item.fileId"
                @click="handleOpen($event)"
                @contextmenu.prevent="openContextMenu(item.fileId, $event)" />
            </section>
          </el-main>

          <!-- main 底部的分页器 -->
          <div class="pagination">
            <el-pagination :page-size="10" :total="totalProjectNum" background layout="prev, pager, next"
              @current-change="handlePageChange" />
          </div>

        </el-col>
      </el-container>

      <!-- 确认删除 弹窗 -->
      <el-dialog v-model="deleteDialogVisible" :show-close="false" title="提示" width="30%">
        <span>是否确认删除？</span>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="handleDelete(false)">取消</el-button>
            <el-button type="primary" @click="handleDelete(true)">确认</el-button>
          </span>
        </template>
      </el-dialog>

      <!-- 右键菜单 -->
      <div class="context-menu" v-show="contextMenuVisible" ref="contextMenu">
        <button @click.stop="deleteDialogVisible = true; contextMenuVisible = false">删除</button>
      </div>

  </div>
  </el-container>
  </div>
  <script>
    const Folder = {
      template: `
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="114" height="114" style="border-color: rgba(0,0,0,0);border-width: bpx;border-style: undefined" filter="none">
          <g>
          <path d="M22.816 12.192h5.76v-2.272c0-0.96-0.768-1.76-1.76-1.76h-6.56l-0.576-1.056c-0.446-0.855-1.323-1.431-2.335-1.44h-12.161c-0.992 0-1.792 0.8-1.792 1.792v4.736h19.424zM22.816 13.376h-20.8l1.376 11.264c0 0.928 0.8 1.696 1.792 1.696h21.632c0.96 0 1.76-0.768 1.76-1.696l1.44-11.264h-7.2z" 
          fill="rgba(133.875,194.055,250.92,1)"></path>
          </g>
        </svg>
      `
    }

    const File = {
      template: `
        <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="90" height="90" style="border-color: rgba(0,0,0,0);border-width: bpx;border-style: undefined" filter="none">
          <g>
          <path d="M14 2l-8 8h8z" fill="rgba(133.11,169.065,205.02,1)"></path>
          <path d="M16 2v10h-10v18h22v-28z" fill="rgba(133.11,169.065,205.02,1)"></path>
          </g>
        </svg>
      `
    }
    // 搜索图标
    const Search = {
      template: `
      <svg class="icon-btn" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="22" height="22" style="border-color: rgba(0,0,0,0);border-width: bpx;border-style: undefined" filter="none">
        <g>
        <path d="M30.428 28.814l-7.377-7.377c1.614-2.073 2.766-4.611 2.766-7.606 0-6.681-5.301-11.983-11.986-11.983-6.681 0-11.983 5.301-11.983 11.987 0 6.685 5.301 11.987 11.987 11.987 2.997 0 5.533-1.155 7.608-2.769l7.374 7.374 1.614-1.614zM4.146 13.83c0-5.301 4.38-9.681 9.683-9.681 5.301 0 9.679 4.38 9.679 9.683 0 2.303-0.924 4.608-2.307 6.222l-1.155 1.152c-1.614 1.383-3.919 2.305-6.223 2.305-5.301 0-9.681-4.383-9.681-9.683z" fill="rgba(222.105,218.025,218.025,1)"></path>
        </g>
      </svg>
      `
    }
    // 描述图标
    const Description = {
      template: `
        <svg class="icon-btn-stroke" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="16" height="16" style="border-color: rgba(0,0,0,0);border-width: bpx;border-style: undefined" filter="none">
          <g>
          <path d="M5 10H43M5 24H43M5 38H43" stroke="#bbb" stroke-width="4" fill="none"></path>
          </g>
        </svg>
      `
    }
    // 头像图标
    const User = {
      template: `
      <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="20" height="20" style="border-color: rgba(0,0,0,0);border-width: bpx;border-style: undefined" filter="none">
        <g>
        <path d="M27.488 25.696c-7.36-4.448-15.008-4.608-22.4-0.352-2.624 1.504-4.288 3.488-5.088 5.632h32c-0.704-2.048-2.208-3.904-4.512-5.28zM16 1.024c5.216 0 9.408 4.16 9.44 9.344s-4.192 9.44-9.376 9.504c-5.248 0.032-9.44-4.192-9.472-9.472 0-5.216 4.16-9.376 9.408-9.376z" fill="rgba(250.92,245.05499999999998,245.05499999999998,1)"></path>
        </g>
      </svg>
      `
    }
    // 复制图标
    const Copy = {
      template: `
      <svg class="icon-btn" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2307" width="20" height="20">
        <path d="M755 965.1H174c-42.8 0-77.7-34.8-77.7-77.7V238.9c0-42.8 34.8-77.7 77.7-77.7h581c42.8 0 77.7 34.8 77.7 77.7v648.5c0 42.9-34.9 77.7-77.7 77.7zM174.1 208.5c-16.8 0-30.4 13.6-30.4 30.4v648.5c0 16.8 13.6 30.4 30.4 30.4h581c16.8 0 30.4-13.6 30.4-30.4V238.9c0-16.8-13.6-30.4-30.4-30.4h-581z" 
          fill="#aaa" p-id="2308"></path>
        <path d="M910.4 809.7c-13.1 0-23.6-10.6-23.6-23.6V137.6c0-16.8-13.6-30.4-30.4-30.4h-581c-13.1 0-23.6-10.6-23.6-23.6S262.4 60 275.4 60h581c42.8 0 77.7 34.8 77.7 77.7v648.5c-0.1 12.9-10.7 23.5-23.7 23.5z" 
          fill="#aaa" p-id="2309"></path>
        <path d="M646.3 397.7H282.7c-13.1 0-23.6-10.6-23.6-23.6 0-13.1 10.6-23.6 23.6-23.6h363.6c13.1 0 23.6 10.6 23.6 23.6 0.1 13-10.5 23.6-23.6 23.6zM646.3 586.8H282.7c-13.1 0-23.6-10.6-23.6-23.6s10.6-23.6 23.6-23.6h363.6c13.1 0 23.6 10.6 23.6 23.6s-10.5 23.6-23.6 23.6zM525.1 776H282.7c-13.1 0-23.6-10.6-23.6-23.6s10.6-23.6 23.6-23.6h242.4c13.1 0 23.6 10.6 23.6 23.6S538.2 776 525.1 776z" 
          fill="#aaa" p-id="2310"></path>
      </svg>
      `
    }
    // 侧边栏 项目文件 图标
    const SideBarProj = {
      template: `
      <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="18" height="18" style="border-width: bpx;border-style: undefined" filter="none">
        <g>
        <path d="M5 8C5 6.89543 5.89543 6 7 6H19L24 12H41C42.1046 12 43 12.8954 43 14V40C43 41.1046 42.1046 42 41 42H7C5.89543 42 5 41.1046 5 40V8Z" fill="none" stroke="rgba(85.935,83.89500000000001,83.89500000000001,1)" stroke-width="4" stroke-linejoin="round"></path>
        <path d="M43 22H5" stroke="rgba(85.935,83.89500000000001,83.89500000000001,1)" stroke-width="4" stroke-linejoin="round" fill="none"></path>
        <path d="M5 16V28" stroke="rgba(85.935,83.89500000000001,83.89500000000001,1)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"></path>
        <path d="M43 16V28" stroke="rgba(85.935,83.89500000000001,83.89500000000001,1)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"></path>
        </g>
      </svg>
      `
    }
    // 侧边栏 协作文件 图标
    const SideBarCoop = {
      template: `
      <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="18" height="18" style="border-color: rgba(0,0,0,0);border-width: bpx;border-style: undefined" filter="none">
        <g>
          <path d="M40 23V14L31 4H10C8.89543 4 8 4.89543 8 6V42C8 43.1046 8.89543 44 10 44H22" stroke="rgba(85.935,83.89500000000001,83.89500000000001,1)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"></path>
          <rect x="28" y="34" width="14" height="8" fill="none" stroke="rgba(85.935,83.89500000000001,83.89500000000001,1)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></rect>
          <path d="M38 34V31C38 29.3431 36.6569 28 35 28C33.3431 28 32 29.3431 32 31V34" stroke="rgba(85.935,83.89500000000001,83.89500000000001,1)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"></path>
          <path d="M30 4V14H40" stroke="rgba(85.935,83.89500000000001,83.89500000000001,1)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"></path>
        </g>
      </svg>
      `
    }

    // 项目文件 组件
    const FileItem = {
      components: {
        File,
        Description
      },
      props: ['name'],
      template: `
      <section class="file-item">
        <div class="item">
          <i><File/></i>
          <div class="file-info">
            <span class="project-name ellipsis-text-overflow" v-text="name"></span>
          </div>
        </div>
      </section>
      `
    }
    const app = Vue.createApp({
      components: {
        Folder,
        'copy': Copy,
        'user': User,
        'search': Search,
        'file-item': FileItem,
        'sidebar-proj': SideBarProj,
        'sidebar-coop': SideBarCoop,
      },
      data() {
        return {
          projectId: "",// TODO
          userName: '孜然123456789',
          searchContent: '',
          totalProjectNum: 20,
          projectName: '科研项目xx',
          files: [
            { fileName: "123.png", fileId: "123", url: "https://p26-passport.byteacctimg.com/img/user-avatar/3341427019b0ee60d65d7ed73ad1345b~300x300.image" },
            { fileName: '456.pdf', fileId: "456", url: "http://cdn07.foxitsoftware.cn/pub/foxit/datasheet/phantom/zh_cn/Datasheet_FoxitPhantomPDFStandard.pdf" },
          ],
          uploadFileList: [],
          // 确认删除弹窗
          deleteDialogVisible: false,
          // 右键菜单
          contextMenuVisible: false,
          // 右键菜单选中的 DOM 元素
          contextMenuTarget: null,
        }
      },
      mounted() {
        document.addEventListener("click", (e) => {
          this.removeCurTarget()
        })
        // this.getFiles(1)
      },
      methods: {
        // 📌获取文件列表
        async getFiles(page, limit = 20) {
          const body = {
            page,
            limit,
            type: "1",
            projectId: this.projectId
          }

          const res = await fetch('/project/listProjectInfo', {
            method: "POST",
            body
          })

          const files = await res.json()
            .then(res => {
              this.$message({
                message: "获取项目列表成功",
                type: "success"
              })
              this.totalProjectNum = res.total
              return res.data
            })
            .catch(err => {
              this.$message({
                message: "获取项目列表失败",
                type: "error"
              })
              this.totalProjectNum = 0
              return []
            })

          files.forEach(file => {
            const type = fileType.reduce((match, [type, reg]) => {
              if (match) return match
              const typeMatch = reg.test(file.fileName)
              return !!typeMatch && type
            }, false)

            file.type = type ? type : 'other'
          })
          this.files = files
        },
       
        // TODO:📌翻页
        handlePageChange(curPage) {

        },
        // TODO: 📌搜索
        search() {
          //this.getProjectList(1, this.searchContent)
        },

        // 右键菜单
        openContextMenu(fileId, e) {
          const targetFile = e.target.closest('.file-item')
          if (!targetFile) return;

          this.removeCurTarget()
          this.contextMenuTarget = targetFile
          targetFile.setAttribute('data-target', true)

          const { clientX, clientY } = e
          this.$refs.contextMenu.style.transform = `translate(${clientX}px, ${clientY}px)`
          this.contextMenuVisible = true
        },
        // 移除右键选中的效果
        removeCurTarget() {
          if (!this.contextMenuTarget) return;
          this.contextMenuTarget.removeAttribute('data-target')
          this.contextMenuTarget = null
          this.contextMenuVisible = false
        },
        // 处理确认删除的弹窗
        handleDelete(confirm) {
          if (confirm) {
            const id = this.contextMenuTarget.getAttribute('id')
            this.delete(id)
          }
          this.deleteDialogVisible = false
          this.removeCurTarget()
        },

        // TODO: 📌删除文件
        async delete(fileId) {
          console.log('[delete]', fileId)
        },

        // TODO:打开历史记录
        handldOpen(e) {
          console.log('[open]')
        },
        // 复制用户名
        copy() {
          const userNameElem = document.querySelector('.dropdown > span')
          const range = new Range();
          range.selectNodeContents(userNameElem)

          document.getSelection().removeAllRanges(); // 清除现有选择
          document.getSelection().addRange(range);

          const str = document.getSelection().toString().slice(4)
          if (navigator && navigator.clipboard) {
            navigator.clipboard.writeText(str)
              .then(() => {
                this.$message({
                  message: '复制成功！',
                  type: 'success',
                })
              })
          }
          document.getSelection().removeRange(range);
        },
      },
    })
    app.use(ElementPlus)
    app.mount('#App')

  </script>
</body>

</html>